package org.jetlinks.community.device.web;

import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.hswebframework.web.api.crud.entity.PagerResult;
import org.hswebframework.web.api.crud.entity.QueryOperation;
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
import org.hswebframework.web.authorization.annotation.QueryAction;
import org.hswebframework.web.authorization.annotation.Resource;
import org.jetlinks.community.device.entity.*;
import org.jetlinks.community.device.enums.CommandHiKEnum;
import org.jetlinks.community.device.service.LocalDeviceInstanceService;
import org.jetlinks.community.device.service.LocalDeviceProductService;
import org.jetlinks.community.device.service.VideoPlayService;
import org.jetlinks.community.device.web.response.GatewayDeviceInfo;
import org.jetlinks.core.device.DeviceRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.Collections;
import java.util.List;

/**
 * 网关设备接口
 *
 * @author zhouhao
 * @since 1.0
 */
@RestController
@RequestMapping("/device/media")
@Resource(id = "device-media", name = "视频监控管理")
@Tag(name = "视频监控管理")
public class MediaDeviceController {

    @Autowired
    private LocalDeviceInstanceService instanceService;

    @Autowired
    private LocalDeviceProductService productService;

    @Autowired
    private DeviceRegistry registry;

    @javax.annotation.Resource
    private VideoPlayService videoPlayService;

    /**
     * 获取直播流地址
     * @param id
     * @param liveStreamParam
     * @return
     */
    @GetMapping("/{id}/live")
    public Mono<VideoScreen> getLiveStream(@PathVariable String id, LiveStreamParam liveStreamParam) {
        liveStreamParam.setCameraIndexCode(id);
        return videoPlayService.getLiveStream(liveStreamParam);
    }

    /**
     * 获取直播流地址
     * @param id
     * @param playBackStreamParam
     * @return
     */
    @GetMapping("/{id}/playback")
    public Mono<VideoScreen> getPlaybackStream(@PathVariable String id, PlayBackStreamParam playBackStreamParam) {
        playBackStreamParam.setCameraIndexCode(id);
        playBackStreamParam.setHIKBeginTime();
        playBackStreamParam.setHIKEndTime();

        return videoPlayService.getPlayBackStream(playBackStreamParam);
    }


    @GetMapping("/_query")
    @QueryAction
    @QueryOperation(summary = "视频监控管理")
    public Mono<PagerResult<DeviceInstanceEntity>> queryGatewayDevice(@Parameter(hidden = true) QueryParamEntity param) {
        return param
            .toNestQuery(query -> query.is(DeviceInstanceEntity::getProductId, "gb28181_device"))
            .execute(instanceService::queryPager).defaultIfEmpty(PagerResult.empty());
    }

    @GetMapping("/{id}")
    @QueryAction
    @QueryOperation(summary = "获取监控详情")
    public Mono<GatewayDeviceInfo> getMediaInfo(@PathVariable String id) {
        return Mono.zip(
            instanceService.findById(id),
            instanceService.createQuery()
                           .where()
                           .is(DeviceInstanceEntity::getParentId, id)
                           .fetch()
                           .collectList()
                           .defaultIfEmpty(Collections.emptyList()) ,
            GatewayDeviceInfo::of);
    }

    /**
     * 通过设备id获取预置点id
     * @param id
     * @return
     */
    @GetMapping("/{id}/presets")
    public Mono<List<PresetView>> getPresets(@PathVariable String id) {
        return videoPlayService.getPresets(id);
    }


    @PostMapping("/{id}/preset")
    public Mono<PresetView> addPreset(@Validated @RequestBody PresetView preset, @PathVariable String id) {
        preset.setCameraIndexCode(id);
        return videoPlayService.addPreset(preset);
    }

    @DeleteMapping("/{id}/preset/{presetId}")
    public Mono<Integer> deletePreset(@PathVariable String id, @PathVariable Integer presetId) {
        return videoPlayService.deletePreset(id, presetId);
    }

    @PostMapping("/{id}/preset/{presetId}/_invoke")
    public Mono<Void> invokePreset(@PathVariable String id, @PathVariable Integer presetId) {
        return videoPlayService.invokePreset(id, presetId);
    }

    @PostMapping("/{id}/ptz/{command}")
    public Mono<Void> ptz(@PathVariable String id, @PathVariable String command) {
        return videoPlayService.ptz(id, CommandHiKEnum.valueOf(command));
    }

}
